<template>
      <el-dialog
          :model-value="visible"
          width="60%"
          title="SSH终端"
          @close="dialogClose"
          style="min-width: 1000px;"
          >
        <div class="host-info">
          <el-tag size="large" type="primary">名称：{{row.name}}</el-tag>
          <el-tag size="large" type="success">主机名：{{row.hostname}}</el-tag>
          <el-tag size="large" type="warning">IP地址：{{row.ssh_ip}}</el-tag>
          <el-tag size="large" type="warning">端口：{{row.ssh_port}}</el-tag>
        </div>
        <div ref="xterm" class="terminal" style="height: 500px;margin-top: 20px"/>
     </el-dialog>
</template>

<script>
    import 'xterm/css/xterm.css'
    import { Terminal } from 'xterm'
    import { FitAddon } from 'xterm-addon-fit'
    import {render} from "vue";  // xterm窗口自适应

    export default {
        name: "SSHTerminal",
        props: {
          visible: Boolean,
          row: '',
        },
        data() {
            return {
                term: '',  // term实例
                ws: '', // ws连接
            }
        },
        methods: {
             // 初始化Terminal
            init() {
                this.term = new Terminal({
                    fontSize: 18,
                    convertEol: true, // 启用时，光标将设置为下一行的开头
                    rendererType: 'canvas', // 渲染类型
                    cursorBlink: true, // 光标闪烁
                    cursorStyle: 'bar', // 光标样式 underline
                    theme: {
                      background: '#060101', // 背景色
                      cursor: 'help' // 设置光标
                    }
              })
            },
            // 初始化Websocket
            initSocket() {
              const fitPlugin = new FitAddon()
              fitPlugin.activate(this.term)
              // this.term.loadAddon(fitPlugin)

              // 建立ws连接
              this.ws = new WebSocket(`ws://${process.env.VUE_APP_API_HOST}:${process.env.VUE_APP_API_PORT}/server/terminal/${this.row.ssh_ip}/${this.row.ssh_port}/${this.row.credential.id}/`)

              // 建立ws连接成功后回调
              this.ws.onopen = () => {
                // 将term挂载到标签上
                this.term.open(this.$refs.xterm)
                this.term.focus()
                fitPlugin.fit()
              }

              // 获取后端传回的数据
              this.ws.onmessage = (res) => {
                const reader = new window.FileReader()
                reader.onload = () => this.term.write(reader.result)
                reader.readAsText(res.data, 'utf-8')
              }

              // 用户输入发送到后端
              this.term.onData(data => this.ws.send(JSON.stringify({ data })))

              // 动态设置终端窗口大小
              this.term.onResize(({ cols, rows }) => {
                this.ws.send(JSON.stringify({ resize: [cols, rows] }))
              })
              window.onresize = () => fitPlugin.fit()

              // ws关闭连接
              this.ws.onclose = (e) => {
                  console.log('Websocket关闭：' + e)
              }

            },
            //清理websocket和终端资源
            cleanupSocket(){
              if (this.ws){
                this.ws.close();
              }
              if (this.term){
                this.term.dispose();
              }
            },
            // 点击关闭，子组件通知父组件更新属性
            dialogClose() {
              this.cleanupSocket();
              this.$emit('update:visible', false);  // 父组件必须使用v-model
              window.location.reload()
            },
        },
        watch: {
            visible() {
                this.init();
                this.initSocket();
            }
        }
    }
</script>

<style scoped>
    .host-info .el-tag {
      font-size: 16px;
      margin-right: 5px;
    }
</style>